home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / os / sprite / osfonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-15  |  21.9 KB  |  972 lines

  1. /************************************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ************************************************************************/
  24.  
  25. /* $XConsortium: osfonts.c,v 1.27 89/10/03 16:45:21 keith Exp $ */
  26.  
  27. #include <stdio.h>
  28. #include "Xos.h"
  29. #include <sys/dir.h>
  30. #include <sys/param.h>
  31. #include <sys/stat.h>
  32. #include <errno.h>
  33.  
  34. #include "X.h"
  35. #include "Xmd.h"
  36. #include "Xproto.h"
  37. #include "dixfontstr.h"
  38. #include "fontstruct.h"
  39. #include "osstruct.h"
  40. #include "misc.h"
  41. #include "opaque.h"
  42. #include "dixstruct.h"
  43.  
  44. #include "fonttype.h"
  45. #include "fontdir.h"
  46.  
  47. extern int errno;
  48.  
  49. extern void CopyISOLatin1Lowered();
  50. extern Atom    MakeAtom();
  51. extern char *defaultFontPath;
  52.  
  53. static int    ReadFontAlias ();
  54. static FontFile    FindFontFile ();
  55. static int    ReadFontDir ();
  56.  
  57. FontPathPtr        GetFontPath ();
  58.  
  59. /* maintained for benefit of GetFontPath */
  60. static FontPathPtr searchList = (FontPathPtr)NULL;
  61.  
  62. void
  63. FreeFontRecord(pFP)
  64.     FontPathPtr pFP;
  65. {
  66.     int i;
  67.     for (i=0; i<pFP->npaths; i++) {
  68.         xfree(pFP->paths[i]);
  69.     }
  70.     xfree(pFP->paths);
  71.     xfree(pFP->length);
  72.     xfree(pFP->osPrivate);
  73.     xfree(pFP);
  74. }
  75.  
  76. static FontPathPtr
  77. MakeFontPathRecord(size)
  78.     unsigned    size;
  79. {
  80.     FontPathPtr fp;    
  81.  
  82.     fp = (FontPathPtr)xalloc(sizeof(FontPathRec));
  83.     if (fp) {
  84.     fp->npaths = 0;
  85.     fp->size = size;
  86.     fp->length = (int *)xalloc(size * sizeof(int));
  87.     fp->paths = (char **)xalloc(size * sizeof(char *));
  88.     fp->osPrivate = (pointer *)xalloc(size * sizeof(pointer));
  89.     if (!fp->length || !fp->paths || !fp->osPrivate) {
  90.         xfree(fp->length);
  91.         xfree(fp->paths);
  92.         xfree(fp->osPrivate);
  93.         xfree(fp);
  94.         fp = (FontPathPtr)NULL;
  95.     }
  96.     }
  97.     return fp;
  98. }
  99.  
  100. static int
  101. AddFontPathElement(path, element, length, fontDir)
  102.     FontPathPtr path;
  103.     char *element;
  104.     int  length;
  105.     Bool fontDir;
  106. {
  107.     int index = path->npaths;
  108.     FontTable table;
  109.     char *nelt;
  110.     int status;
  111.  
  112.     if (fontDir)
  113.     {
  114.     status = ReadFontDir(element, &table, path);
  115.     if (status != Success)
  116.         return status;
  117.     }
  118.     nelt = (char *)xalloc(length + 1);
  119.     if (!nelt)
  120.     return BadAlloc;
  121.     if (index >= path->size)
  122.     {
  123.     int size = path->size << 1;
  124.     int *nlength;
  125.     char **npaths;
  126.     pointer *npriv;
  127.  
  128.     nlength = (int *)xrealloc(path->length, size*sizeof(int));
  129.     npaths = (char **)xrealloc(path->paths, size*sizeof(char *));
  130.     npriv = (pointer *)xrealloc(path->osPrivate, size * sizeof(pointer));
  131.     if (nlength && npaths && npriv)
  132.     {
  133.         path->size = size;
  134.         path->length = nlength;
  135.         path->paths = npaths;
  136.         path->osPrivate = npriv;
  137.     }
  138.     else
  139.     {
  140.         xfree(nlength);
  141.         xfree(npaths);
  142.         xfree(npriv);
  143.         return BadAlloc;
  144.     }
  145.     }
  146.     path->length[index] = length;
  147.     path->paths[index] = nelt;
  148.     strncpy(nelt, element, length);
  149.     nelt[length] = '\0';
  150.     path->osPrivate[index] = (pointer)table;
  151.     path->npaths++;
  152.     return Success;
  153. }
  154.  
  155. static void
  156. FreeFontPath(path)
  157.     FontPathPtr path;
  158. {
  159.     int     i, j;
  160.     FontPtr font;
  161.     FontTable table;
  162.  
  163.     /* 
  164.      * First all the back pointers for the outstanding fonts must be smashed
  165.      * to NULL so that when the font is freed, the removal from the (now
  166.      * freed) previous table can be skipped.
  167.      */
  168.     if (path) {
  169.     for (i = 0; i < path->npaths; i++) {
  170.         table = (FontTable) path->osPrivate[i];
  171.         for (j = 0; j < table->file.used; j++) {
  172.         if ((font = (FontPtr) table->file.ff[j].private) != NullFont)
  173.             font->osPrivate = NULL;
  174.         }
  175.         FreeFontTable (table);
  176.     }
  177.     FreeFontRecord (path);
  178.     }
  179. }
  180.  
  181. /*
  182.  * Font paths are not smashed to lower case. (Note "/usr/lib/X11/fonts")
  183.  *
  184.  * Allow initial font path to have names separated by spaces tabs or commas
  185.  */
  186. int
  187. SetDefaultFontPath(name)
  188.     char *    name;
  189. {
  190.     register char *start, *end;
  191.     char dirName[MAXPATHLEN];
  192.     FontPathPtr path;
  193.     int status;
  194.  
  195.     path = MakeFontPathRecord(3);
  196.     if (!path)
  197.     return BadAlloc;
  198.     end = name;
  199.     for (;;) {
  200.     start = end;
  201.     while ((*start == ' ') || (*start == '\t') || (*start == ','))
  202.         start++;
  203.     if (*start == '\0')
  204.         break;
  205.     end = start;
  206.     while ((*end != ' ') && (*end != '\t') && (*end != ',') &&
  207.         (*end != '\0'))
  208.        end++;
  209.     strncpy(dirName, start, end - start);
  210.     dirName[end - start] = '\0';
  211.     if (dirName[strlen(dirName) - 1] != '/')
  212.         strcat(dirName, "/");
  213.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  214.     if (status != Success)
  215.     {
  216.         FreeFontPath(path);
  217.         return status;
  218.     }
  219.     }
  220.     FreeFontPath(searchList);
  221.     searchList = path;
  222.     return Success;
  223. }
  224.  
  225. int
  226. SetFontPath(client, npaths, countedStrings)
  227.     ClientPtr    client;
  228.     unsigned    npaths;
  229.     char *    countedStrings;
  230. {
  231.     int i;
  232.     unsigned char * bufPtr = (unsigned char *)countedStrings;
  233.     char dirName[MAXPATHLEN];
  234.     unsigned int n;
  235.     FontPathPtr path;
  236.     int status;
  237.  
  238.     if (npaths == 0)
  239.     return SetDefaultFontPath(defaultFontPath); /* this frees old paths */
  240.  
  241.     path = MakeFontPathRecord(npaths);
  242.     if (!path)
  243.     return BadAlloc;
  244.     for (i=0; i<npaths; i++) {
  245.     n = (unsigned int)(*bufPtr++);
  246.     strncpy(dirName, (char *) bufPtr, (int) n);
  247.     dirName[n] = '\0';
  248.     if (dirName[n - 1] != '/')
  249.         strcat(dirName, "/");
  250.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  251.     if (status != Success)
  252.     {
  253.         FreeFontPath(path);
  254.         client->errorValue = i;
  255.         return status;
  256.     }
  257.     bufPtr += n;
  258.     }
  259.     FreeFontPath(searchList);
  260.     searchList = path;
  261.     return Success;
  262. }
  263.  
  264. FontPathPtr
  265. GetFontPath()
  266. {
  267.     return(searchList);
  268. }
  269.  
  270. static int
  271. FindFileType(name)
  272.     char *name;
  273. {
  274.     register int i, j, k;
  275.     char *ext;
  276.  
  277.     k = strlen(name);
  278.     for (i = 0; fontFileReaders[i].extension; i++) {
  279.     ext = fontFileReaders[i].extension;
  280.     j = strlen(ext);
  281.     if ((k > j) && (strcmp(ext, name + k - j) == 0))
  282.         return i;
  283.     }
  284.     return -1;
  285. }
  286.  
  287. static int
  288. ReadFontDir(directory, ptable, path)
  289.     char    *directory;
  290.     FontTable    *ptable;
  291.     FontPathPtr path;
  292. {
  293.     char file_name[MAXPATHLEN];
  294.     char font_name[MAXPATHLEN];
  295.     char dir_file[MAXPATHLEN];
  296.     char BUF[BUFSIZ];
  297.     FILE *file;
  298.     int count, i, status;
  299.     FontTable matchTable;
  300.     FontTable table = NullTable;
  301.  
  302.     strcpy(dir_file, directory);
  303.     if (directory[strlen(directory) - 1] != '/')
  304.      strcat(dir_file, "/");
  305.     strcat(dir_file, FontDirFile);
  306.     file = fopen(dir_file, "r");
  307.     if (file)
  308.     {
  309.     setbuf (file, BUF);
  310.     count = fscanf(file, "%d\n", &i);
  311.     if ((count == EOF) || (count != 1)) {
  312.         fclose(file);
  313.         return BadValue;
  314.     }
  315.     table = MakeFontTable(directory, count+10);
  316.     for (;;) {
  317.         count = fscanf(file, "%s %[^\n]\n", file_name, font_name);
  318.         if (count == EOF)
  319.         break;
  320.         if (count != 2) {
  321.             fclose(file);
  322.         return BadValue;
  323.         }
  324.         if (!FindFontFile (path, font_name, 0, FALSE, &matchTable) &&
  325.         (FindFileType (file_name) >= 0)) {
  326.         i = AddFileEntry(table, file_name, False);
  327.         if (i < 0) {
  328.             fclose(file);
  329.             return BadAlloc;
  330.         }
  331.         i = AddNameEntry(table, font_name, i);
  332.         if (i <= 0) {
  333.             fclose(file);
  334.             return (i ? BadAlloc : BadValue);
  335.         }
  336.         }
  337.     }
  338.     fclose(file);
  339.     }
  340.     else if (errno != ENOENT)
  341.     {
  342.     return BadValue;
  343.     }
  344.     status = ReadFontAlias(directory, FALSE, &table, path);
  345.     if (status != Success)
  346.     {
  347.     FreeFontTable(table);
  348.     return status;
  349.     }
  350.     if (!table)
  351.     return BadValue;
  352.     /*
  353.      * At this point, no more entries will be made in file table. This means
  354.      * that it will not be realloced and we can put pointers (rather than
  355.      * indices into the table.
  356.      */
  357.     for (i = 0; i < table->name.used; i++)
  358.     table->name.fn[i].u.ff = &table->file.ff[table->name.fn[i].u.index];
  359.  
  360.     *ptable = table;
  361.     return Success;
  362. }
  363.  
  364. /* 
  365.  * Make each of the file names an automatic alias for each of the files.
  366.  * This assumes that all file names are of the form <root>.<extension>.
  367.  */
  368.  
  369. static Bool
  370. AddFileNameAliases(table, path)
  371.     FontTable table;
  372.     FontPathPtr path;
  373. {
  374.     int i, typeIndex;
  375.     Boolean found;
  376.     FontTable    matchTable;
  377.  
  378.     char copy[MAXPATHLEN];
  379.  
  380.     for (i = 0; i < table->file.used; i++) {
  381.     if (table->file.ff[i].alias)
  382.         continue;
  383.     strcpy(copy, table->file.ff[i].name);
  384.     typeIndex = FindFileType(copy);
  385.     copy[strlen(copy) - strlen(fontFileReaders[typeIndex].extension)] = NUL;
  386.     CopyISOLatin1Lowered ((unsigned char *)copy, (unsigned char *)copy,
  387.                   strlen (copy));
  388.     (void)  FindNameInFontTable(table, copy, &found);
  389.     if (!found && !FindFontFile (path, copy, 0, FALSE, &matchTable)) {
  390.         if (AddNameEntry(table, copy, i) < 0)
  391.         return FALSE;
  392.     }
  393.     }
  394.     return TRUE;
  395. }
  396.  
  397. /*
  398.  * parse the font.aliases file.  Format is:
  399.  *
  400.  * alias font-name
  401.  *
  402.  * To imbed white-space in an alias name, enclose it like "font name" 
  403.  * in double quotes.  \ escapes and character, so
  404.  * "font name \"With Double Quotes\" \\ and \\ back-slashes"
  405.  * works just fine.
  406.  */
  407.  
  408. /*
  409.  * token types
  410.  */
  411.  
  412. static int    lexAlias (), lexc ();
  413.  
  414. # define NAME        0
  415. # define NEWLINE    1
  416. # define DONE        2
  417. # define EALLOC        3
  418.  
  419. static int
  420. ReadFontAlias(directory, isFile, ptable, path)
  421.     char      *directory;
  422.     Bool      isFile;
  423.     FontTable *ptable;
  424.     FontPathPtr path;
  425. {
  426.     char alias[MAXPATHLEN];
  427.     char font_name[MAXPATHLEN];
  428.     char alias_file[MAXPATHLEN];
  429.     char buf[BUFSIZ];
  430.     FILE *file;
  431.     int i;
  432.     FontTable matchTable;
  433.     FontTable table;
  434.     int    token;
  435.     Bool found;
  436.     char *lexToken;
  437.     int status = Success;
  438.  
  439.     table = *ptable;
  440.     strcpy(alias_file, directory);
  441.     if (!isFile)
  442.     {
  443.     if (directory[strlen(directory) - 1] != '/')
  444.         strcat(alias_file, "/");
  445.     strcat(alias_file, AliasFile);
  446.     }
  447.     file = fopen(alias_file, "r");
  448.     if (!file)
  449.     return ((errno == ENOENT) ? Success : BadValue);
  450.     setbuf (file, buf);
  451.     if (!table)
  452.     *ptable = table = MakeFontTable (directory, 10);
  453.     if (!table)
  454.     return BadAlloc;
  455.     while (status == Success) {
  456.     token = lexAlias (file, &lexToken);
  457.     switch (token) {
  458.     case NEWLINE:
  459.         break;
  460.     case DONE:
  461.         fclose (file);
  462.         return Success;
  463.     case EALLOC:
  464.         status = BadAlloc;
  465.         break;
  466.     case NAME:
  467.         strcpy (alias, lexToken);
  468.         token = lexAlias (file, &lexToken);
  469.         switch (token) {
  470.         case NEWLINE:
  471.         if (strcmp (alias, "FILE_NAMES_ALIASES"))
  472.             status = BadValue;
  473.         else if (!AddFileNameAliases (table, path))
  474.             status = BadAlloc;
  475.         break;
  476.         case DONE:
  477.         status = BadValue;
  478.         break;
  479.         case EALLOC:
  480.         status = BadAlloc;
  481.         break;
  482.         case NAME:
  483.         CopyISOLatin1Lowered ((unsigned char *)alias,
  484.                       (unsigned char *)alias,
  485.                       strlen (alias));
  486.         CopyISOLatin1Lowered ((unsigned char *)font_name,
  487.                       (unsigned char *)lexToken,
  488.                       strlen (lexToken));
  489.         (void) FindNameInFontTable (table, alias, &found);
  490.         if (!found &&
  491.             !FindFontFile (path, alias, 0, FALSE, &matchTable)) {
  492.             i = AddFileEntry(table, font_name, True);
  493.             if (i < 0) {
  494.             status = BadAlloc;
  495.             } else {
  496.             i = AddNameEntry(table, alias, i);
  497.             if (i <= 0)
  498.                 status = (i ? BadAlloc : BadValue);
  499.             }
  500.         }
  501.         break;
  502.         }
  503.     }
  504.     }
  505.     fclose(file);
  506.     return status;
  507. }
  508.  
  509. # define QUOTE        0
  510. # define WHITE        1
  511. # define NORMAL        2
  512. # define END        3
  513. # define NL        4
  514.  
  515. static int    charClass;
  516.  
  517. static int
  518. lexAlias (file, lexToken)
  519. FILE    *file;
  520. char    **lexToken;
  521. {
  522.     int        c;
  523.     char        *t;
  524.     enum state { Begin, Normal, Quoted } state;
  525.     int        count;
  526.  
  527.     static char    *tokenBuf = (char *)NULL;
  528.     static int    tokenSize = 0;
  529.  
  530.     t = tokenBuf;
  531.     count = 0;
  532.     state = Begin;
  533.     for (;;) {
  534.         if (count == tokenSize) {
  535.             int nsize;
  536.             char *nbuf;
  537.  
  538.             nsize = tokenSize ? (tokenSize << 1) : 64;
  539.             nbuf = (char *)xrealloc(tokenBuf, nsize);
  540.             if (!nbuf)
  541.             return EALLOC;
  542.             tokenBuf = nbuf;
  543.             tokenSize = nsize;
  544.             t = tokenBuf + count;
  545.         }
  546.         c = lexc (file);
  547.         switch (charClass) {
  548.         case QUOTE:
  549.             switch (state) {
  550.             case Begin:
  551.             case Normal:
  552.                 state = Quoted;
  553.                 break;
  554.             case Quoted:
  555.                 state = Normal;
  556.                 break;
  557.             }
  558.             break;
  559.         case WHITE:
  560.             switch (state) {
  561.             case Begin:
  562.                 continue;
  563.             case Normal:
  564.                 *t = '\0';
  565.                 *lexToken = tokenBuf;
  566.                 return NAME;
  567.             case Quoted:
  568.                 break;
  569.             }
  570.             /* fall through */
  571.         case NORMAL:
  572.             switch (state) {
  573.             case Begin:
  574.                 state = Normal;
  575.             }
  576.             *t++ = c;
  577.             ++count;
  578.             break;
  579.         case END:
  580.         case NL:
  581.             switch (state) {
  582.             case Begin:
  583.                 *lexToken = (char *)NULL;
  584.                 return charClass == END ? DONE : NEWLINE;
  585.             default:
  586.                 *t = '\0';
  587.                 *lexToken = tokenBuf;
  588.                 ungetc (c, file);
  589.                 return NAME;
  590.             }
  591.         }
  592.     }
  593. }
  594.  
  595. static int
  596. lexc (file)
  597. FILE    *file;
  598. {
  599.     int    c;
  600.     c = getc (file);
  601.     switch (c) {
  602.     case EOF:
  603.         charClass = END;
  604.         break;
  605.     case '\\':
  606.         c = getc (file);
  607.         if (c == EOF)
  608.             charClass = END;
  609.         else
  610.             charClass = NORMAL;
  611.         break;
  612.     case '"':
  613.         charClass = QUOTE;
  614.         break;
  615.     case ' ':
  616.     case '\t':
  617.         charClass = WHITE;
  618.         break;
  619.     case '\n':
  620.         charClass = NL;
  621.         break;
  622.     default:
  623.         charClass = NORMAL;
  624.         break;
  625.     }
  626.     return c;
  627. }
  628.  
  629. static Bool
  630. SearchDirectory(index, pat, fontList, limit)
  631.     int index;
  632.     char *pat;
  633.     FontPathPtr fontList;
  634.     unsigned limit;
  635. {
  636.     int i, res, len, head, tail;
  637.     FontTable table;
  638.  
  639.     if (!searchList)
  640.     return TRUE;
  641.     table = (FontTable)searchList->osPrivate[index];
  642.     i = SetupWildMatch(table, pat, (char *)NULL, &head, &tail, &len);
  643.     while (i < table->name.used)
  644.     {
  645.     res = Match(table->name.fn[i].name, pat, head, tail, len);
  646.     if (res > 0)
  647.     {
  648.         if (AddFontPathElement(fontList, table->name.fn[i].name,
  649.                    strlen(table->name.fn[i].name), False))
  650.         return FALSE;
  651.         if (fontList->npaths >= limit)
  652.         break;
  653.     }
  654.     else if (res < 0)
  655.         break;
  656.     i++;
  657.     }
  658.     return TRUE;
  659. }
  660.  
  661. /*******************************************************************
  662.  *  ExpandFontNamePattern
  663.  *
  664.  *    Returns a FontPathPtr with at most max-names, of names of fonts
  665.  *      matching
  666.  *    the pattern.  The pattern should use the ASCII encoding, and
  667.  *      upper/lower case does not matter.  In the pattern, the '?' character
  668.  *    (octal value 77) will match any single character, and the character '*'
  669.  *    (octal value 52) will match any number of characters.  The return
  670.  *    names are in lower case.
  671.  *
  672.  *      Used only by protocol request ListFonts & ListFontsWithInfo
  673.  *******************************************************************/
  674.  
  675. FontPathPtr
  676. ExpandFontNamePattern(lenpat, countedPattern, maxNames)
  677.     unsigned    lenpat;
  678.     char    *countedPattern;
  679.     unsigned    maxNames;
  680. {
  681.     char    *pattern;
  682.     int        i;
  683.     FontPathPtr    fpr;
  684.  
  685.     if (!searchList)
  686.     return (FontPathPtr)NULL;
  687.     /* random number, this is a guess, but it hardly matters. */
  688.     fpr = MakeFontPathRecord ((unsigned) 100);
  689.     if (!fpr)
  690.     return (FontPathPtr)NULL;
  691.     pattern = (char *)ALLOCATE_LOCAL (lenpat + 1);
  692.     if (!pattern)
  693.     {
  694.     FreeFontRecord(fpr);
  695.     return (FontPathPtr)NULL;
  696.     }
  697.     /*
  698.      * make a pattern which is guaranteed NULL-terminated
  699.      */
  700.     CopyISOLatin1Lowered((unsigned char *)pattern,
  701.              (unsigned char *)countedPattern,
  702.              (int) lenpat);
  703.  
  704.     for ( i=0; i<searchList->npaths; i++)
  705.     {
  706.     if (!SearchDirectory(i, pattern, fpr, maxNames))
  707.     {
  708.         FreeFontRecord(fpr);
  709.         return (FontPathPtr)NULL;
  710.     }
  711.     if (fpr->npaths >= maxNames)
  712.         break;
  713.     }
  714.     DEALLOCATE_LOCAL(pattern);
  715.     return fpr;
  716. }
  717.  
  718. /*
  719.  * OS interface to reading font files. This is not called by the dix routines
  720.  * but rather by any of the pseudo-os-independent font internalization
  721.  * routines.
  722.  */
  723.  
  724. int
  725. FontFileRead(buf, itemsize, nitems, fid)
  726.     char    *buf;
  727.     unsigned    itemsize;
  728.     unsigned    nitems;
  729.     FID        fid;
  730. {
  731.     return fread( buf, (int) itemsize, (int) nitems, (FILE *)fid);
  732. }
  733.  
  734. int
  735. FontFileSkip(bytes, fid)
  736.     unsigned    bytes;
  737.     FID        fid;
  738. {
  739.     struct stat    stats;
  740.     int c;
  741.  
  742.     fstat(fileno((FILE *)fid), &stats);
  743.     if ((stats.st_mode & S_IFMT) == S_IFREG)
  744.     c = fseek((FILE *) fid, (long) bytes, 1);
  745.     else
  746.     while (bytes-- && ((c = getc((FILE *)fid)) != EOF))
  747.         ;
  748.     return c;
  749. }
  750.  
  751. /*
  752.  * When a font is unloaded (destroyed) it is necessary to remove the pointer
  753.  * in the font table since it is no longer valid. This means that the
  754.  * "obvious" technique of putting the FontPtr into the table when an aliased
  755.  * font is loaded would mean that the table would have to be searched for
  756.  * any matching entry. To avoid scanning all the tables when a font is FontPtr
  757.  * destroyed, the Font has a back pointer to the FontFile (in the table) where
  758.  * it was entered.
  759.  *
  760.  * So that aliases will not also keep a copy of the FontPtr in their FontTable
  761.  * entries, a pointer to the "resolved" FontTable is actually kept and the
  762.  * indirection is taken.
  763.  *
  764.  * A slight non-conformance to the protocol is possible here. If any
  765.  * FontTable is for a file that does not load (i.e. was changed since the
  766.  * font.dirs was created), then that font name will not work even though it
  767.  * should because of wild carding or the use of a search path. The moral is
  768.  * is that the font.dirs should be correct.
  769.  *
  770.  * To prevent circular aliases from crashing the server (due to the recursive
  771.  * nature of FindFontFile) a limit of MAX_LINKS is put on the length of a
  772.  * chain that will be followed.
  773.  */
  774.  
  775. #define MAX_LINKS 20
  776.  
  777. static FontFile 
  778. FindFontFile(path, fontname, depth, followAliases, table)
  779.     FontPathPtr path;
  780.     char *    fontname;
  781.     int        depth;
  782.     Bool    followAliases;    
  783.     FontTable    *table;     /* returned */
  784. {
  785.     int     nameIndex, i;
  786.     Bool found;
  787.     FontFile ff, resolved;
  788.  
  789.     if (!path || (depth >= MAX_LINKS))
  790.     return NullFontFile;
  791.     for (i = 0; i < path->npaths; i++)
  792.     {
  793.     *table = (FontTable) path->osPrivate[i];
  794.     nameIndex = FindNameInFontTable (*table, fontname, &found);
  795.     if (!found)
  796.         continue;
  797.     ff = (*table)->name.fn[nameIndex].u.ff;
  798.     if (!ff->alias || !followAliases)
  799.         return ff;
  800.     if (resolved = FindFontFile (path, ff->name, depth + 1, TRUE, table))
  801.     {
  802.         ff->private = (Opaque) resolved;
  803.         return resolved;
  804.     }
  805.     }
  806.     return NullFontFile;
  807. }
  808.  
  809. #if defined(SYSV) && !defined(hpux)        /* hpux does have vfork */
  810. #define vfork() fork()
  811. #endif
  812.  
  813. #ifdef apollo               /* Domain/OS has vfork but it breaks the graphics layer */
  814. #define vfork() fork()
  815. #endif
  816.  
  817. static int
  818. FontFilter(fp, filter)
  819.     FILE *fp;
  820.     char **filter;
  821. {
  822.     int pfd[2];
  823.     int pid;
  824.  
  825.     if (pipe(pfd) < 0) {
  826.     fclose(fp);
  827.     return (-1);
  828.     }
  829.     switch(pid = vfork()) {
  830.     case 0:
  831.     dup2(fileno(fp), 0);
  832.     close(fileno(fp));
  833.     dup2(pfd[1], 1);
  834.     close(pfd[0]);
  835.     close(pfd[1]);
  836.     execvp(filter[0], filter);
  837.     _exit(127);
  838.     case -1:
  839.     close(pfd[0]);
  840.     close(pfd[1]);
  841.     fclose(fp);
  842.     return(-1);
  843.     default:
  844.     dup2(pfd[0], fileno(fp));
  845.     close(pfd[0]);
  846.     close(pfd[1]);
  847.     return(pid);
  848.     }    
  849. }
  850.  
  851. static FILE *
  852. OpenFontFile(table, name, typeIndex, pid)
  853.     FontTable table;
  854.     char     *name;
  855.     int         *typeIndex;
  856.     int      *pid;
  857. {
  858.     char    pathName[MAXPATHLEN];
  859.     FILE   *fp;
  860.     char **filter;
  861.  
  862.     strcpy (pathName, table->directory);
  863.     strcat (pathName, name);
  864.     if ((fp = fopen (pathName, "r")) == (FILE *)NULL)
  865.     return fp;
  866.     *pid = 0;
  867.     *typeIndex = FindFileType (name);
  868.     filter = fontFileReaders[*typeIndex].filter;
  869.     if (filter) {
  870.     *pid = FontFilter(fp, filter);
  871.     if (*pid < 0)
  872.         return (FILE *)NULL;
  873.     }
  874.     return fp;
  875. }
  876.  
  877. static void
  878. CloseFontFile(fp, pid)
  879.     FILE *fp;
  880.     int pid;
  881. {
  882.     int child;
  883.  
  884.     fclose (fp);
  885.     if (pid >= 0)
  886.        do { child = wait(0); } while (child != pid && child != -1);
  887. }
  888.  
  889. FontPtr 
  890. FontFileLoad(fontname, length)
  891.     unsigned    length;
  892.     char *    fontname;
  893. {
  894.     FontPtr    font;
  895.     char    fName[MAXPATHLEN];
  896.     char    buf[BUFSIZ];
  897.     FILE    * fp;
  898.     FontTable    table;
  899.     FontFile    ff;
  900.     int        typeIndex;
  901.     int        cookie;
  902.  
  903.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  904.              (int) length);
  905.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  906.     if (!ff)
  907.     return NullFont;
  908.     if (ff->private != NULL)
  909.     return (FontPtr) ff->private;    /* already loaded */
  910.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  911.     return NullFont;
  912.     setbuf (fp, buf);
  913.     font = (fontFileReaders[typeIndex].loadFont) (fp);
  914.     CloseFontFile(fp, cookie);
  915.     if (font == NullFont)
  916.     return NullFont;
  917.     ff->private = (Opaque) font;
  918.     font->refcnt = 0;
  919.     font->fileType = typeIndex;
  920.     font->osPrivate = (pointer) ff;
  921.     return font;
  922. }
  923.  
  924. /*
  925.  * This either returns an existing font, or if that can't be found,
  926.  * then fills in the FontInfo and FontProp by reading from the disk.
  927.  */
  928.  
  929. Bool
  930. FontFilePropLoad(fontname, length, font, fi, props)
  931.     char    *fontname;
  932.     unsigned int length;
  933.     FontInfoPtr fi;
  934.     DIXFontPropPtr *props;    /* return */
  935.     FontPtr    *font;        /* return */
  936. {
  937.     char    fName[MAXPATHLEN];
  938.     FILE *    fp;
  939.     FontTable    table;
  940.     FontFile    ff;
  941.     Bool    found;
  942.     int        typeIndex;
  943.     char    buf[BUFSIZ];
  944.     int        cookie;
  945.  
  946.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  947.              (int) length);
  948.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  949.     if (!ff)
  950.     return FALSE;
  951.     if (ff->private != NULL) {
  952.     *font = (FontPtr) ff->private;
  953.     return TRUE;
  954.     }
  955.     *font = NullFont;
  956.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  957.     return FALSE;
  958.     setbuf (fp, buf);
  959.     found = (*fontFileReaders[typeIndex].loadProperties) (fp, fi, props);
  960.     CloseFontFile(fp, cookie);
  961.     return found;
  962. }
  963.  
  964. void FontUnload(font)
  965.     FontPtr font;
  966. {
  967.     FontFile ff;
  968.     if ((ff = (FontFile)font->osPrivate) != NULL)
  969.     ff->private = NULL;
  970.     (*fontFileReaders[font->fileType].freeFont)(font);
  971. }
  972.